#include "wavetool.h"

PaintStyle::PaintStyle():colorR(0), colorG(0), colorB(0) ,lineWidth(1.0){
}

PaintStyle::PaintStyle(QColor color, float lineWidth)
{
    colorR = color.redF();
    colorG = color.greenF();
    colorB = color.blueF();
    this->lineWidth = lineWidth;
}

Text2DStyle::Text2DStyle()
{

}

Text2DStyle::Text2DStyle(QColor color, QFont font)
{
    mColor = color;
    mFont = font;
}

CTexturePoint::CTexturePoint()
{
    x = 0; y = 0; z = 0;
    texture = NULL;
    mImg = NULL;
}

CTexturePoint::CTexturePoint(float x, float y, float z){
    this->x = x;
    this->y = y;
    this->z = z;
    texture = NULL;
    mImg = NULL;
}

CTexturePoint::~CTexturePoint()
{
    if (mImg != NULL){
        delete mImg;
        mImg = NULL;
    }
    if (texture != NULL) {
        if(texture->isCreated())
            texture->destroy();
        delete texture;
        texture = NULL;
    }
}

void CTexturePoint::createTexture(bool bDelTexture)
{
    if (mImg == NULL) {
        return;
    }
    if (texture == NULL) {
        texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
    }
    if (bDelTexture)
    {
        //动态绘制坐标，大小不一致
        //通过这种方法来实现动态纹理适应于纹理尺寸会动态变化的情况
        //内存分配会占用一定性能，但在这里影响微乎其微（如果是绘制视频帧，那么就需要提前分配存储，之后动态上传像素数据）
        if (texture->isCreated()) {
            texture->destroy();
        }
        texture->create();
    }
    else {
        if (!texture->isCreated()) {
            texture->create();
        }
    }
    texture->setData(mImg->mirrored());
}

void CTexturePoint::bindImg(QImage *img)
{
    if (img == NULL)
    {
        return;
    }
    if(mImg != NULL){
        delete mImg;
        mImg = NULL;
    }
    mImg = img;
}

CText2DTool::CText2DTool()
{

}

CText2DTool::~CText2DTool()
{

}

void CText2DTool::initGL()
{
    VAO.create();
    QOpenGLVertexArrayObject::Binder bind(&VAO);
    VBO.create();
    VAO.bind();
    VBO.bind();
    static float vertex[]={
        //顶点            //纹理坐标
        -1.0f,-1.0f,    0.0f,0.0f,    //左下
        -1.0f, 1.0f,    0.0f,1.0f,    //左上
        1.0f,-1.0f,    1.0f,0.0f,    //右下
        1.0f, 1.0f,    1.0f,1.0f     //右上
    };
    VBO.allocate(vertex,sizeof (vertex));
    shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,
                     "#version 450 core\n"
                     "attribute vec2 pos;\n"
                     "attribute vec2 texCoord;\n"
                     "varying vec2 outCoord;\n"
                     "void main(void) {\n"
                     "   gl_Position = vec4(pos,0,1);\n"
                     "   outCoord = texCoord;\n"
                     "}\n");
    shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment,
                      "uniform sampler2D texture;\n"
                      "varying vec2 outCoord;\n"
                      "void main(void) {\n"
                      "   gl_FragColor = texture2D(texture, outCoord);\n"  //取颜色
                      "}\n");

    shaderProgram.link();
    shaderProgram.enableAttributeArray(0);
    shaderProgram.enableAttributeArray(1);
    shaderProgram.setAttributeBuffer(0,GL_FLOAT,0,               2,4*sizeof (float));
    shaderProgram.setAttributeBuffer(1,GL_FLOAT,2*sizeof (float),2,4*sizeof (float));
    VAO.release();
    VBO.release();
}

void CText2DTool::drawTextLT(CTexturePoint *tp, GLdouble wx, GLdouble wy)
{
    if (tp == NULL){
        return;
    }
    if (tp ->texture == NULL || tp->mImg == NULL){
        return;
    }
    glViewport(wx, wy, tp->mImg->width(), tp->mImg->height());
    QOpenGLVertexArrayObject::Binder bind(&VAO);
    shaderProgram.bind();
    tp->texture->bind(0);
    glDrawArrays(GL_TRIANGLE_STRIP,0,4);
    shaderProgram.release();
}

void CText2DTool::drawTextRT(CTexturePoint *tp, GLdouble wx, GLdouble wy)
{
    if (tp == NULL){
        return;
    }
    if (tp ->texture == NULL || tp->mImg == NULL){
        return;
    }
    glViewport(wx - tp->mImg->width(), wy, tp->mImg->width(), tp->mImg->height());
    QOpenGLVertexArrayObject::Binder bind(&VAO);
    shaderProgram.bind();
    tp->texture->bind(0);
    glDrawArrays(GL_TRIANGLE_STRIP,0,4);
    shaderProgram.release();
}

CAxisText::CAxisText(int nums)
{
    mNum = nums;
    mTexture = new CTexturePoint*[mNum];
    for(int i = 0; i < mNum; i++){
        mTexture[i] = NULL;
    }
    mBPaint = false;
    mBUpdateTexture = false;
}

CAxisText::~CAxisText()
{
    clear();
    mNum = 0;
}

CAxisText* CAxisText::setText(int index, QString text)
{
    if (index >= mNum){
        return this;
    }
    if (mTexture[index] == NULL){
        mTexture[index] = new CTexturePoint();
    }
    mBPaint = true;
    mBUpdateTexture = true;
    QFontMetrics fontMetrics(mFont);
    QRect bounding= fontMetrics.boundingRect(text);      //获取到字符串的外包矩形
    QImage* img = new QImage(bounding.size(),QImage::Format_ARGB32);
    img->fill(Qt::transparent);                        //使用透明色填充Image
    QPainter painter;
    painter.begin(img);
    painter.setRenderHints(QPainter::TextAntialiasing|QPainter::Antialiasing);  //开启抗锯齿
    painter.setFont(mFont);
    painter.setPen(mColor);
    painter.drawText(QRect(0,0,img->width(),img->height()),Qt::AlignCenter,text);
    painter.end();
    mTexture[index]->bindImg(img);
    return this;
}

CAxisText* CAxisText::setPos(int index, float x, float y, float z)
{
    if (index >= mNum){
        return this;
    }
    if (mTexture[index] == NULL) {
        mTexture[index] = new CTexturePoint();
    }
    mTexture[index]->x = x;
    mTexture[index]->y = y;
    mTexture[index]->z = z;
    return this;
}

void CAxisText::createTextures()
{
    if (!mBPaint) {
        return;
    }
    if (mBUpdateTexture) {
        CTexturePoint* texture = NULL;
        for (int i =0; i < mNum; i++){
            texture = mTexture[i];
            if (texture != NULL) {
                texture->createTexture();
            }
        }
    }
    mBUpdateTexture = false;
}

void CAxisText::clearTextures()
{
    mBPaint = false;
    mBUpdateTexture = false;
}

void CAxisText::clear()
{
    if (mTexture != NULL) {
        for(int i = 0; i < mNum; i++){
            if (mTexture[i] != NULL) {
                delete mTexture[i];
                mTexture[i] = NULL;
            }
        }
        delete[] mTexture;
        mTexture = NULL;
    }
}

int CAxisText::getNumAndPaint()
{
    if (mBPaint){
        return mNum;
    }
    return 0;
}

CLegend::CLegend()
{
    rect = QRect(0, 0, 10, 80);
    scale = 1.0f;
}

CLegend::~CLegend()
{
    colors.clear();
}

void CLegend::paintColorCard(QPaintDevice * pd)
{
    if (colors.length() == 0) {
        return;
    }
    QPainter colorPainter(pd);
    colorPainter.setPen(Qt::NoPen);
    QImage colorImage  = QImage(30, 100, QImage::Format_ARGB32);
    float tmp = colors.length() / 100.0f;
    for (int i = 29; i >= 0; i--) {
        for (int j = 0; j < 100;j++) {
            int index = int((99 - j) * tmp);
            colorImage.setPixel(QPoint(i,j), colors[index].rgb());
        }
    }
    colorPainter.drawImage(rect,colorImage);
    colorPainter.end();
}

void CLegend::setColor(QColor color)
{
    colors.append(color);
}

void CLegend::randomColor(int num)
{
    QColor colorGreen = QColor(Qt::green);
    QColor colorRed = QColor(Qt::red);
    QColor colorBlue = QColor(Qt::blue);
    num = int(num / 2);
    for (int i = 0; i < num;i++) {
        float p = i / float(num);
        colors.append(QColor(int((1.0-p) * colorGreen.red() + p * colorBlue.red() + 0.5),
               int((1.0-p) * colorGreen.green() + p * colorBlue.green() + 0.5),
                           int((1.0-p) * colorGreen.blue() + p * colorBlue.blue() + 0.5)));
    }

    for (int i = 0; i < num; i++) {
        float p = i / float(num);
        colors.append(QColor(int((1.0-p) * colorBlue.red() + p * colorRed.red() + 0.5),
                            int((1.0-p) * colorBlue.green() + p * colorRed.green() + 0.5),
                            int((1.0-p) * colorBlue.blue() + p * colorRed.blue() + 0.5)));
    }
}

void CLegend::mappingRange(float min, float max) {
    if (colors.length() == 0) {
        return;
    }
    if (max <= min + 0.001f) {
        max = min + 0.001f;
    }
    scale = colors.length() / (max - min);
}

QColor CLegend::mapping(int val, int min, int max)
{
    int len = colors.length();
    if (len == 0 || max == min) {
        return colors[0];
    }
    scale = len / float((max - min));
    int index = int(scale * val);
    if (index >= len){
        index = len - 1;
    }
    return colors[index];
}

void CLegend::mapping(float val, float *r, float *g, float *b)
{
    if (colors.length() == 0) {
        return;
    }
    int index = int(scale * val);
    if (index >= colors.length()){
        index = colors.length() - 1;
    }
    *r = colors[index].redF();
    *g = colors[index].greenF();
    *b = colors[index].blueF();
}
